package org.tgcloud.group.core;

import org.springframework.data.redis.core.*;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author suxiaolin
 * @date 2019-03-21 08:20
 */
public class RedisUtil {

    private static RedisTemplate redisTemplate;

    private RedisUtil() {
    }

    public static void setRedisTemplate(RedisTemplate redisTemplate) {
        RedisUtil.redisTemplate = redisTemplate;
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     * @return 缓存的对象
     */
    public static <T> ValueOperations<String, T> setCacheObject(String key, T value) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value);
        return operation;
    }

    public static <T> ValueOperations<String, T> setCacheObject(String key, T value, Long timeout, TimeUnit timeUnit) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value, timeout, timeUnit);
        return operation;
    }

    /**
     * 获取对象的过期时间：seconds
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public static Long getObjectExpireTime(String key) {
        ValueOperations<String, Object> operation = redisTemplate.opsForValue();
        return redisTemplate.getExpire(key);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public static <T> T getCacheObject(String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 判断key是否存在
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public static boolean existKey(String key) {
        return redisTemplate.hasKey(key);
    }

    //获取新增计数
    public static <T> T getSetCacheIncrement(String key, Integer num) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        if (redisTemplate.hasKey(key)) {
            return RedisUtil.getCacheObject(key);
        } else {
            operation.increment(key, num);
            return operation.get(key);
        }
    }

    //增加计数
    public static <T> T setCacheIncrement(String key, Integer num) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.increment(key, num);
        return operation.get(key);
    }

    //减少计数
    public static <T> T setCacheDecrement(String key, Integer num) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.decrement(key, num);
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public static void deleteObject(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 删除集合对象
     *
     * @param collection
     */
    public static void deleteObject(Collection collection) {
        redisTemplate.delete(collection);
    }

    /**
     * 缓存List数据
     *
     * @param key      缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public static <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
        ListOperations listOperation = redisTemplate.opsForList();
        if (null != dataList) {
            int size = dataList.size();
            for (int i = 0; i < size; i++) {
                listOperation.leftPush(key, dataList.get(i));
            }
        }
        return listOperation;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public static <T> List<T> getCacheList(String key) {
        if (redisTemplate.hasKey(key) == null || !redisTemplate.hasKey(key)) {
            return null;
        }
        List<T> dataList = new ArrayList<T>();
        ListOperations<String, T> listOperation = redisTemplate.opsForList();
        Long size = listOperation.size(key);

        for (int i = 0; i < size; i++) {
            dataList.add(listOperation.index(key, i));
        }
        return dataList;
    }

    /**
     * 缓存Set
     *
     * @param key     缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public static <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext()) {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public static <T> Set<T> getCacheSet(String key) {
        Set<T> dataSet = new HashSet<T>();
        BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
        Long size = operation.size();
        for (int i = 0; i < size; i++) {
            dataSet.add(operation.pop());
        }
        return dataSet;
    }

    /**
     * 获得缓存的set的长度
     *
     * @param key
     * @return
     */
    public static Long getCacheSetSize(String key) {
        Set<Object> dataSet = new HashSet<Object>();
        BoundSetOperations<String, Object> operation = redisTemplate.boundSetOps(key);
        Long size = operation.size();
        return size;
    }


    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public static <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {

        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }

//    public static <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap, Long expire, TimeUnit unit) {
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        if (null != dataMap && !dataMap.isEmpty()) {
//            hashOperations.putAll(key, dataMap);
//        }
//        hashOperations.getOperations().expire(key, expire, unit);
//        return hashOperations;
//    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public static <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap, Long expire, TimeUnit unit) {

        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        hashOperations.getOperations().expire(key, expire, unit);
        return hashOperations;
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public static HashOperations<String, String, BigDecimal> setCacheMapBiDecimal(String key, Map<String, BigDecimal> dataMap) {

        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, BigDecimal> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue().toString());
            }
        }
        return hashOperations;
    }

    /**
     * 缓存Map某一个属性
     *
     * @param key
     * @param pro
     * @param object
     * @return
     */
    public static <T> HashOperations<String, String, T> setCacheMapPro(String key, String pro, T object) {

        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != pro) {
            hashOperations.put(key, pro, object);
        }
        return hashOperations;
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public static <T> Map<String, T> getCacheMap(String key) {
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        return map;
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public static <T> HashOperations<String, Integer, T> setCacheIntegerMap(String key, Map<Integer, T> dataMap) {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<Integer, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public static <T> Map<Integer, T> getCacheIntegerMap(String key) {
        Map<Integer, T> map = redisTemplate.opsForHash().entries(key);
        return map;
    }

    /**
     * push
     *
     * @param key     缓存的键值
     * @param message 待缓存的数据
     * @return 缓存的对象
     */
    public static Boolean lpush(String key, String message) {
        return !ObjectUtils.isEmpty(redisTemplate.opsForList().leftPush(key, message));
    }

    /**
     * 阻塞队列, 出队列
     *
     * @param queue        需要阻塞的队列名称
     * @param blockSeconds 阻塞的秒数
     * @return
     */
    public static String blpop(String queue, Integer blockSeconds) {
        return (String) redisTemplate.opsForList().leftPop(queue, blockSeconds, TimeUnit.SECONDS);
    }

    /**
     * 获得缓存的z set
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public static <T> Set<T> getCacheZSet(String key) {
        if (redisTemplate.hasKey(key) == null || !redisTemplate.hasKey(key)) {
            return null;
        }
        ZSetOperations<String, T> listOperation = redisTemplate.opsForZSet();
        return listOperation.range(key, 0, -1);
    }

    /**
     * @param
     * @return
     * @Author SGY
     * @Date 2020/7/10 18:18
     * @Description // 批量删除
     **/
    public static void batchDel(String prefix) {
        Set<String> keys = redisTemplate.keys(prefix);
        for (String key : keys) {
            RedisUtil.deleteObject(key);
        }
    }


    //获取计数
    public static <T> Long getSetCacheIncrementLong(String key, long num) {
        if (!redisTemplate.hasKey(key)) {
            ValueOperations<String, Long> operation = redisTemplate.opsForValue();
            operation.increment(key, num);
        }
        return getCacheLong(key);
    }

    //增加计数
    public static <T> Long setCacheIncrementLong(String key, long num) {
        ValueOperations<String, Long> operation = redisTemplate.opsForValue();
        operation.increment(key, num);
        return getCacheLong(key);
    }

    //减少计数
    public static <T> Long setCacheDecrementLong(String key, long num) {
        ValueOperations<String, Long> operation = redisTemplate.opsForValue();
        operation.decrement(key, num);
        return getCacheLong(key);
    }

    public static <T> Long getCacheLong(String key) {
        Object valueObj = redisTemplate.opsForValue().get(key);
        if (valueObj == null) {
            return null;
        } else if (valueObj instanceof Integer) {
            Integer obj = (Integer) valueObj;
            return obj.longValue();
        } else if (valueObj instanceof Long)  {
            return (long) valueObj;
        } else {
            return null;
        }
    }

    /**
     * 查找匹配的key
     *
     * @param pattern
     * @return
     */
    public static Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }


}
